package com.aso.common.sp;

import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

/**
 * @Description ：ISharedPreference 接口实现类提供增、删、改、查 等功能
 * @Author itsdf07
 * @Time 2017/11/30
 */

public class SharedPreferenceImpl implements ISharedPreference {
    /**
     * 默认的文件名
     */
    private static final String FILE_NAME = "shared_preferences";

    private SharedPreferences mSP;

    private static ISharedPreference mISP;

    /**
     * 对象锁
     */
    private static final Object lock = new Object();

    /**
     * 获取 ISharedPreference 对象
     *
     * @param context
     * @return
     */
    public static ISharedPreference getSP(Context context) {
        return getSP(context, FILE_NAME);
    }

    /**
     * 获取ISharedPreference对象
     *
     * @param context
     * @param fileName 存储数据的文件名
     * @return
     */
    public static ISharedPreference getSP(Context context, String fileName) {
        synchronized (lock) {
            if (mISP == null) {
                initSP(context, fileName);
            }
        }
        return mISP;
    }

    /**
     * 初始化IPreference对象
     *
     * @param context
     * @param fileName
     */
    private static synchronized void initSP(Context context, String fileName) {
        if (mISP == null) {
            mISP = new SharedPreferenceImpl(context, fileName);
        }
    }

    /**
     * 实例化一个新的 SharedPreference 管理器：使用默认存储文件
     *
     * @param context
     */
    public SharedPreferenceImpl(Context context) {
        mSP = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
    }

    /**
     * 实例化一个新的 SharedPreference 管理器
     *
     * @param context
     * @param fileName 存储数据的文件名
     */
    public SharedPreferenceImpl(Context context, String fileName) {
        if (TextUtils.isEmpty(fileName)) {
            fileName = FILE_NAME;
        }
        mSP = context.getSharedPreferences(fileName, Context.MODE_PRIVATE);
    }

    @Override
    public void put(String key, Object value) {
        SharedPreferences.Editor edit = mSP.edit();
        put(edit, key, value);
        edit.apply();
    }

    /**
     * 保存一个Map集合
     *
     * @param map
     */
    @Override
    public <T> void putAll(Map<String, T> map) {
        SharedPreferences.Editor edit = mSP.edit();
        for (Map.Entry<String, T> entry : map.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            put(edit, key, value);
        }
        edit.apply();
    }

    @Override
    public void putAll(String key, List<String> list) {
        putAll(key, list, new ComparatorImpl());
    }

    @Override
    public void putAll(String key, List<String> list, Comparator<String> comparator) {
        Set<String> set = new TreeSet<>(comparator);
        for (String value : list) {
            set.add(value);
        }
        mSP.edit().putStringSet(key, set).apply();
    }

    /**
     * 根据key取出一个数据
     *
     * @param key 键
     */
    @SuppressWarnings("unchecked")
    @Override
    public <T> T get(String key, DataType type) {
        return (T) getValue(key, type);
    }

    @Override
    public Map<String, ?> getAll() {
        return mSP.getAll();
    }

    @Override
    public List<String> getAll(String key) {
        List<String> list = new ArrayList<String>();
        Set<String> set = get(key, DataType.STRING_SET);
        for (String value : set) {
            list.add(value);
        }
        return list;
    }

    @Override
    public void remove(String key) {
        mSP.edit().remove(key).apply();
    }

    @Override
    public void removeAll(List<String> keys) {
        SharedPreferences.Editor edit = mSP.edit();
        for (String k : keys) {
            edit.remove(k);
        }
        edit.apply();
    }

    @Override
    public void removeAll(String[] keys) {
        removeAll(Arrays.asList(keys));
    }

    @Override
    public boolean contains(String key) {
        return mSP.contains(key);
    }

    @Override
    public void clear() {
        mSP.edit().clear().apply();
    }

    @Override
    public String getString(String key) {
        return get(key, DataType.STRING);
    }

    @Override
    public float getFloat(String key) {
        return get(key, DataType.FLOAT);
    }

    @Override
    public int getInteger(String key) {
        return get(key, DataType.INTEGER);
    }

    @Override
    public long getLong(String key) {
        return get(key, DataType.LONG);
    }

    @Override
    public Set<String> getSet(String key) {
        return get(key, DataType.STRING_SET);
    }

    @Override
    public boolean getBoolean(String key) {
        return get(key, DataType.BOOLEAN);
    }

    /**
     * 保存数据
     *
     * @param editor
     * @param key
     * @param obj
     */
    @SuppressWarnings("unchecked")
    private void put(SharedPreferences.Editor editor, String key, Object obj) {
        // key 不为null时再存入，否则不存储
        if (key != null) {
            if (obj instanceof Integer) {
                editor.putInt(key, (Integer) obj);
            } else if (obj instanceof Long) {
                editor.putLong(key, (Long) obj);
            } else if (obj instanceof Boolean) {
                editor.putBoolean(key, (Boolean) obj);
            } else if (obj instanceof Float) {
                editor.putFloat(key, (Float) obj);
            } else if (obj instanceof Set) {
                editor.putStringSet(key, (Set<String>) obj);
            } else if (obj instanceof String) {
                editor.putString(key, String.valueOf(obj));
            }
        }
    }

    /**
     * 根据key和类型取出数据
     *
     * @param key
     * @return
     */
    private Object getValue(String key, DataType type) {
        switch (type) {
            case INTEGER:
                return mSP.getInt(key, -1);
            case FLOAT:
                return mSP.getFloat(key, -1f);
            case BOOLEAN:
                return mSP.getBoolean(key, false);
            case LONG:
                return mSP.getLong(key, -1L);
            case STRING:
                return mSP.getString(key, null);
            case STRING_SET:
                return mSP.getStringSet(key, null);
            default: // 默认取出String类型的数据
                return null;
        }
    }

    /**
     * 默认比较器，当存储List集合中的String类型数据时，没有指定比较器，就使用默认比较器
     */
    public class ComparatorImpl implements Comparator<String> {

        @Override
        public int compare(String lhs, String rhs) {
            return lhs.compareTo(rhs);
        }
    }

}
